package com.TeacherInfoServer.listener;

import com.TeacherInfoServer.exception.JobNumberNotExistException;
import com.TeacherInfoServer.exception.JobNumberRepeatedException;
import com.TeacherInfoServer.pojo.DTO.TeacherDTO;
import com.TeacherInfoServer.pojo.entity.DoctoralSupervisor;
import com.TeacherInfoServer.pojo.excelImport.DoctoralSupervisorExcel;
import com.TeacherInfoServer.common.service.DoctoralSupervisorService;
import com.TeacherInfoServer.common.service.TeacherService;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import jakarta.validation.Validator;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Data
@Component
public class DoctoralSupervisorListener implements ReadListener<DoctoralSupervisorExcel> {

    @Autowired
    private DoctoralSupervisorService doctoralSupervisorService;
    @Autowired
    private TeacherService teacherService;
    @Autowired
    private Validator validator;
    private final List<DoctoralSupervisor> doctoralSupervisorList = new ArrayList<>();
    private final List<DoctoralSupervisor> updateList = new ArrayList<>();
    private final List<DoctoralSupervisor> addList = new ArrayList<>();
    private final Set<String> teacherIdSet = new HashSet<>();
    private Integer record;

    @Override
    public void invoke(DoctoralSupervisorExcel doctoralSupervisorExcel, AnalysisContext analysisContext) {
        Set<ConstraintViolation<DoctoralSupervisorExcel>> violations = validator.validate(doctoralSupervisorExcel);
        if (violations.isEmpty()){
            TeacherDTO teacherDTO = teacherService.getOne(doctoralSupervisorExcel.getTeacherId()).getData();
            if (teacherDTO != null && teacherDTO.getTeacherName().equals(doctoralSupervisorExcel.getTeacherName())){
                if (!teacherIdSet.contains(doctoralSupervisorExcel.getTeacherId())){
                    DoctoralSupervisor doctoralSupervisor =
                            new DoctoralSupervisor(null,
                                    doctoralSupervisorExcel.getTeacherId(),
                                    doctoralSupervisorExcel.getObtainDate(),
                                    doctoralSupervisorExcel.getObtainSchool(),1,null);
                    doctoralSupervisorList.add(doctoralSupervisor);
                    teacherIdSet.add(doctoralSupervisor.getTeacherId());
                } else {
                    throw new JobNumberRepeatedException();
                }
            } else {
                if (teacherDTO == null) {
                    throw new JobNumberNotExistException();
                } else {
                    throw new RuntimeException("工号与教师名不匹配：" + teacherDTO.getTeacherId());
                }
            }
        } else {
            String errorMessage = violations.iterator().next().getMessage();
            throw new ConstraintViolationException(errorMessage, violations);
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        List<DoctoralSupervisor> doctoralSupervisors = doctoralSupervisorService.list();
        doctoralSupervisorList.forEach(doctoralSupervisor -> {
            Optional<DoctoralSupervisor> dbDoctoralSupervisorOptional = doctoralSupervisors.stream()
                    .filter(dbDoctoralSupervisor -> doctoralSupervisor.getTeacherId().equals(dbDoctoralSupervisor.getTeacherId()))
                    .findFirst();
            dbDoctoralSupervisorOptional.ifPresent(dbDoctoralSupervisor -> {
                doctoralSupervisor.setId(dbDoctoralSupervisor.getId());
                updateList.add(doctoralSupervisor);
            });
            if (dbDoctoralSupervisorOptional.isEmpty()) {
                addList.add(doctoralSupervisor);
            }
        });
        List<DoctoralSupervisor> mergedList = Stream.concat(updateList.stream(), addList.stream())
                .collect(Collectors.toList());
        doctoralSupervisorService.saveOrUpdateBatch(mergedList);
        setRecord(mergedList.size());
        initList();
    }

    public void initList(){
        doctoralSupervisorList.clear();
        updateList.clear();
        addList.clear();
        teacherIdSet.clear();
    }
}
